import {
  useControlController,
  useNamespace,
  useUIStore,
} from '@ibiz-template/vue3-util';
import {
  defineComponent,
  h,
  onUnmounted,
  PropType,
  resolveComponent,
  VNode,
  renderSlot,
  VNodeArrayChildren,
  computed,
  ref,
  watch,
} from 'vue';
import { IDEGrid, IDEGridColumn, IDEGridGroupColumn } from '@ibiz/model-core';
import {
  GridController,
  IControlProvider,
  ScriptFactory,
} from '@ibiz-template/runtime';
import { NOOP } from '@ibiz-template/core';
import { createUUID } from 'qx-util';
import {
  IGridProps,
  useAppGridBase,
  useGridHeaderStyle,
  useGridDraggable,
  useITableEvent,
} from './grid-control.util';
import './grid.scss';
import { useRowEditPopover } from '../row-edit-popover/use-row-edit-popover';
import { usePagination } from '../../../util';

/**
 * 绘制成员的attrs
 * @author lxm
 * @date 2024-03-19 03:48:00
 * @param {IDEFormDetail} model
 * @return {*}  {IParams}
 */
function renderAttrs(model: IDEGridColumn, params: IParams): IParams {
  const attrs: IParams = {};
  model.controlAttributes?.forEach(item => {
    if (item.attrName && item.attrValue) {
      attrs[item.attrName!] = ScriptFactory.execSingleLine(item.attrValue!, {
        ...params,
      });
    }
  });
  return attrs;
}

// 绘制除分组列之外的表格列
export function renderColumn(
  c: GridController,
  model: IDEGridColumn,
  renderColumns: IDEGridColumn[],
  index: number,
): VNode | null {
  const { codeName: columnName, width } = model;
  const columnC = c.columns[columnName!];
  const columnState = c.state.columnStates.find(
    item => item.key === columnName,
  )!;

  // 如果没有配置自适应列，则最后一列变为自适应列
  const widthFlexGrow =
    columnC.isAdaptiveColumn ||
    (!c.hasAdaptiveColumn && index === renderColumns.length - 1);

  const widthName = widthFlexGrow ? 'min-width' : 'width';
  // 表格列自定义
  return (
    <el-table-column
      label={model.caption}
      prop={columnName}
      {...{ [widthName]: width }}
      fixed={columnState.fixed}
      sortable={model.enableSort ? 'custom' : false}
      align={model.align?.toLowerCase() || 'center'}
    >
      {{
        default: ({ row }: IData): VNode | null => {
          let elRow = row; // element表格数据
          if (row.isGroupData) {
            // 有第一条数据时，分组那一行绘制第一条数据
            elRow = row.first;
          }

          const rowState = c.findRowState(elRow);
          if (rowState) {
            const comp = resolveComponent(c.providers[columnName!].component);
            return h(comp, {
              controller: columnC,
              row: rowState,
              key: elRow.tempsrfkey + columnName,
              attrs: renderAttrs(model, {
                ...c.getEventArgs(),
                data: rowState.data,
              }),
            });
          }
          return null;
        },
      }}
    </el-table-column>
  );
}

// 绘制表格列
export function renderChildColumn(
  c: GridController,
  model: IDEGridColumn,
  renderColumns: IDEGridColumn[],
  index: number,
): VNode | null {
  if (model.columnType === 'GROUPGRIDCOLUMN') {
    const childColumns =
      (model as IDEGridGroupColumn).degridColumns?.filter(
        item => !item.hideDefault && !item.hiddenDataItem,
      ) || [];
    const { width } = model;
    const align = model.align?.toLowerCase() || 'center';
    return (
      <el-table-column
        prop={model.codeName}
        label={model.caption}
        min-width={width}
        align={align}
      >
        {{
          default: (): VNodeArrayChildren => {
            return childColumns.map((column, index2) => {
              return renderChildColumn(c, column, renderColumns, index2);
            });
          },
        }}
      </el-table-column>
    );
  }
  return renderColumn(c, model, renderColumns, index);
}

export const GridControl = defineComponent({
  name: 'IBizGridControl',
  props: {
    modelData: { type: Object as PropType<IDEGrid>, required: true },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    provider: { type: Object as PropType<IControlProvider> },
    /**
     * 部件行数据默认激活模式
     * - 0 不激活
     * - 1 单击激活
     * - 2 双击激活(默认值)
     *
     * @type {(number | 0 | 1 | 2)}
     */
    mdctrlActiveMode: { type: Number, default: undefined },
    singleSelect: { type: Boolean, default: undefined },
    rowEditOpen: { type: Boolean, default: undefined },
    isSimple: { type: Boolean, required: false },
    data: { type: Array<IData>, required: false },
    loadDefault: { type: Boolean, default: true },
  },
  setup(props, { slots }) {
    const c = useControlController<GridController>(
      (...args) => new GridController(...args),
    );
    const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`);

    const { zIndex } = useUIStore();
    c.state.zIndex = zIndex.increment();

    const {
      tableRef,
      onRowClick,
      onDbRowClick,
      onSelectionChange,
      onSortChange,
      handleRowClassName,
      handleHeaderCellClassName,
    } = useITableEvent(c);
    const { onPageChange, onPageRefresh, onPageSizeChange } = usePagination(c);

    const { headerCssVars } = useGridHeaderStyle(tableRef, ns);
    const { cleanup = NOOP } = useGridDraggable(tableRef, ns, c);

    const renderNoData = (): VNode | null => {
      // 未加载不显示无数据
      const { isLoaded } = c.state;
      if (isLoaded) {
        const quickToolbar = c.model.controls?.find(
          item => item.name === `${c.model.name}_quicktoolbar`,
        );
        if (quickToolbar) {
          return (
            <iBizToolbarControl
              modelData={quickToolbar}
              context={c.context}
              params={c.params}
              class={ns.b('quick-toolbar')}
            ></iBizToolbarControl>
          );
        }
        return (
          <iBizNoData
            text={c.model.emptyText}
            emptyTextLanguageRes={c.model.emptyTextLanguageRes}
            enableShowImage={c.state.hideNoDataImage}
          ></iBizNoData>
        );
      }
      // 给null 表格会绘制默认的无数据
      return <div></div>;
    };
    const {
      tableData,
      renderColumns,
      defaultSort,
      summaryMethod,
      spanMethod,
      headerDragend,
    } = useAppGridBase(c, props as IGridProps);

    const { renderPopover } = useRowEditPopover(tableRef, c);

    // 绘制批操作工具栏
    const renderBatchToolBar = (): VNode | undefined => {
      const batchToolbar = c.model.controls?.find(item => {
        return item.name === `${c.model.name!}_batchtoolbar`;
      });
      if (!batchToolbar || c.state.singleSelect) {
        return;
      }
      return (
        <div
          class={[
            ns.b('batch-toolbar'),
            ns.is('show', c.state.selectedData.length > 0),
          ]}
        >
          <div class={ns.b('batch-toolbar-content')}>
            <div class={ns.b('batch-toolbar-text')}>
              {ibiz.i18n.t('control.common.itemsSelected', {
                length: c.state.selectedData.length,
              })}
            </div>
            <div class={ns.b('batch-toolbar-separator')}>|</div>
            <iBizToolbarControl
              modelData={batchToolbar}
              context={c.context}
              params={c.params}
              class={ns.b('batch-toolbar-items')}
            ></iBizToolbarControl>
          </div>
        </div>
      );
    };
    // 绘制表格列
    const renderTableColumn = (
      model: IDEGridColumn,
      index: number,
    ): VNode | null => {
      if (slots[model.id!]) {
        return renderSlot(slots, model.id!, {
          model,
          data: c.state.items,
        });
      }
      return renderChildColumn(c, model, renderColumns.value, index);
    };

    // 绘制拖动图标列
    const renderDragIconColumn = () => {
      return (
        <el-table-column
          class-name={ns.e('drag-icon')}
          type='default'
          width='16'
        >
          {{
            default: () => {
              return (
                <svg
                  viewBox='0 0 16 16'
                  class='icon'
                  xmlns='http://www.w3.org/2000/svg'
                  height='1em'
                  width='1em'
                  focusable='false'
                >
                  <g id='drag-icon/drag--' stroke-width='1' fill-rule='evenodd'>
                    <g
                      id='drag-icon'
                      transform='translate(5 1)'
                      fill-rule='nonzero'
                    >
                      <path
                        d='M1 2a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM1 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-4 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-4 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z'
                        id='drag-icon-air'
                      ></path>
                    </g>
                  </g>
                </svg>
              );
            },
          }}
        </el-table-column>
      );
    };

    onUnmounted(() => {
      zIndex.decrement();
      if (cleanup !== NOOP) {
        cleanup();
      }
    });

    // 是否可以加载更多
    const isLodeMoreDisabled = computed(() => {
      if (c.model.pagingMode !== 2) {
        return true;
      }
      return (
        c.state.items.length >= c.state.total ||
        c.state.isLoading ||
        c.state.total <= c.state.size
      );
    });

    // 无限滚动元素
    const infiniteScroll = ref<IData>();
    // 无限滚动元素标识
    const infiniteScrollKey = ref<string>(createUUID());

    watch(
      () => c.state.curPage,
      () => {
        if (
          c.state.curPage === 1 &&
          (c.model.pagingMode === 2 || c.model.pagingMode === 3)
        ) {
          infiniteScrollKey.value = createUUID();
          const containerEl =
            infiniteScroll.value?.ElInfiniteScroll?.containerEl;
          if (containerEl) {
            containerEl.lastScrollTop = 0;
            containerEl.scrollTop = 0;
          }
        }
      },
    );

    return {
      c,
      ns,
      tableRef,
      tableData,
      renderColumns,
      renderTableColumn,
      onDbRowClick,
      onRowClick,
      onSelectionChange,
      onSortChange,
      onPageChange,
      onPageSizeChange,
      onPageRefresh,
      handleRowClassName,
      handleHeaderCellClassName,
      renderNoData,
      summaryMethod,
      spanMethod,
      headerDragend,
      renderPopover,
      defaultSort,
      renderBatchToolBar,
      headerCssVars,
      renderDragIconColumn,
      isLodeMoreDisabled,
      infiniteScroll,
      infiniteScrollKey,
    };
  },
  render() {
    if (!this.c.state.isCreated) {
      return;
    }
    const state = this.c.state;
    const defaultExpandAll = this.c.controlParams.defaultexpandall === 'true';

    return (
      <iBizControlBase
        class={[
          this.ns.is('show-header', !this.c.state.hideHeader),
          this.ns.is('enable-page', this.c.state.enablePagingBar),
          this.ns.is('enable-group', this.c.model.enableGroup),
          this.ns.is('single-select', state.singleSelect),
          this.ns.is('empty', state.items.length === 0),
          this.ns.is('enable-customized', this.c.model.enableCustomized),
        ]}
        controller={this.c}
        style={this.headerCssVars}
      >
        {
          <el-table
            ref={'tableRef'}
            class={this.ns.e('table')}
            default-sort={this.defaultSort}
            border
            show-header={!this.c.state.hideHeader}
            show-summary={this.c.enableAgg}
            summary-method={this.summaryMethod}
            highlight-current-row={state.singleSelect}
            row-class-name={this.handleRowClassName}
            header-cell-class-name={this.handleHeaderCellClassName}
            row-key={'tempsrfkey'}
            data={this.tableData}
            default-expand-all={defaultExpandAll}
            span-method={this.spanMethod}
            onRowClick={this.onRowClick}
            onRowDblclick={this.onDbRowClick}
            onSelectionChange={this.onSelectionChange}
            onSortChange={this.onSortChange}
            onHeaderDragend={this.headerDragend}
            tooltip-effect={'light'}
            scrollbar-always-on={true}
            {...this.$attrs}
          >
            {{
              empty: this.renderNoData,
              default: (): VNodeArrayChildren => {
                return [
                  this.c.enableRowEditOrder && this.renderDragIconColumn(),
                  !state.singleSelect && (
                    <el-table-column
                      class-name={this.ns.e('selection')}
                      type='selection'
                      width='55'
                    ></el-table-column>
                  ),
                  this.renderColumns.map((model, index) => {
                    return this.renderTableColumn(model, index);
                  }),
                ];
              },
              append: () => {
                return [
                  <div
                    ref={'infiniteScroll'}
                    key={this.infiniteScrollKey}
                    v-infinite-scroll={() => this.c.loadMore()}
                    infinite-scroll-distance={10}
                    infinite-scroll-disabled={this.isLodeMoreDisabled}
                  ></div>,
                  this.c.model.pagingMode === 3 &&
                    !(
                      this.c.state.items.length >= this.c.state.total ||
                      this.c.state.isLoading ||
                      this.c.state.total <= this.c.state.size
                    ) && (
                      <div class={this.ns.e('load-more-button')}>
                        <el-button text onClick={() => this.c.loadMore()}>
                          {ibiz.i18n.t('control.common.loadMore')}
                        </el-button>
                      </div>
                    ),
                  this.renderPopover(),
                ];
              },
            }}
          </el-table>
        }
        {this.c.state.enablePagingBar && this.c.model.pagingMode === 1 && (
          <iBizPagination
            total={state.total}
            curPage={state.curPage}
            size={state.size}
            totalPages={state.totalPages}
            onChange={this.onPageChange}
            onPageSizeChange={this.onPageSizeChange}
            onPageRefresh={this.onPageRefresh}
          ></iBizPagination>
        )}
        {this.c.model.enableCustomized && !this.c.state.hideHeader && (
          <div class={this.ns.b('setting-box')}>
            <iBizGridSetting
              columnStates={state.columnStates}
              controller={this.c}
            ></iBizGridSetting>
          </div>
        )}
        {this.renderBatchToolBar()}
      </iBizControlBase>
    );
  },
});
